// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: yuxuan

#pragma once

#include <experimental/filesystem>
#include <fstream>
#include <string>
#include <vector>

#include "coin2/base/log.h"

namespace coin2::strategy::support {
class CsvWriter {
 public:
  CsvWriter(
      const std::experimental::filesystem::path& path,
      const std::vector<std::string>& columns)
      : row_size_(columns.size()) {
    of_.open(path, std::ofstream::out);
    of_ << std::setprecision(12);
    ss_ << std::setprecision(12);
    WriteRow(columns);
  }

  ~CsvWriter() {
    if (of_.is_open()) {
      of_.flush();
      of_.close();
    }
  }

  template <class T>
  void WriteRow(const std::vector<T>& row) {
    CHECK(row.size() == row_size_) << row.size() << " " << row_size_;
    if (!row.empty()) {
      of_ << row[0];
      for (int i = 1; i < row.size(); ++i) {
        of_ << "," << row[i];
      }
    }
    of_ << std::endl;
  }

  void Flush() { of_.flush(); }

  template <class T>
  void AddItems(const std::vector<T>& items) {
    for (const T& item : items) {
      AddItem<T>(item);
    }
  }

  template <class T>
  void AddItem(const T& item) {
    if (item_counter_ > 0) {
      ss_ << delimiter_ << item;
    } else {
      ss_ << item;
    }
    ++item_counter_;
  }

  void WriteItems() {
    CHECK(item_counter_ == row_size_) << item_counter_ << " " << row_size_;
    item_counter_ = 0;
    ss_ << std::endl;
    of_ << ss_.str();
    ss_.str(std::string());
  }

 private:
  std::ofstream of_;
  std::stringstream ss_;
  int item_counter_{0};
  const int row_size_;
  const char delimiter_{','};
};
}  // namespace coin2::strategy::support
